<?php

namespace App\Libs\Payment;

use App\Libs\Wechat\RefundGateway;
use Pay\Pay;

class RockyPayLibrary2
{
    protected $appId;
    protected $payInstance;
    protected $driver;
    protected $config;

    public function __construct($config = [], $driver = 'wechat')
    {
        info('params', func_get_args());
        if (empty($config)) {
            $config = config('payment.weibu');
        }
        $this->appId = data_get($config, $driver.'.'.'app_id', '');
        $this->driver      = $driver;
        $pay               = new Pay($config);
        $this->payInstance = $pay->driver($driver);
        $this->config      = $config;



//        $this->appId       = config('payment.' . $appName . '.' . $driver . '.app_id', '');
//        $this->driver      = $driver;
//        $pay               = new Pay(config('payment.' . $appName), []);
//        $this->payInstance = $pay->driver($driver);
//        $this->config      = config('payment.' . $appName);
    }

    /**
     * 支付
     * @param $order
     * @param $payMethod
     * @param array $option
     * @return mixed|null
     */
    public function payment($payMethod, array $option)
    {
        // Todo 增加其他支付方式

        switch ($payMethod) {
            case 'wx_mp':
                return $this->wxMpPay($option);
            case 'wx_app':
                return $this->wxAppPay($option);
            case 'wx_wap':
                return $this->wxWapPay($option);
            case 'wx_transfer':
                return $this->wxTransFerPay($option);
            case 'wx_refund':
                return $this->wxRefundPay($option);
            default:
                throw new \LogicException("不支持的支付方式", 500);
        }
    }

    /**
     * 查询订单
     * @param $outTradeNo
     * @return mixed
     */
    public function wxQueryOrder($outTradeNo, $paymentMethod = 'mp')
    {
        $driver = $this->payInstance->gateway($paymentMethod);
        return $driver->find($outTradeNo);
    }

    /**
     * 微信h5支付
     * @param  $order
     * @param array $option
     * @return null
     */
    protected function wxWapPay(array $option)
    {
        $driver = $this->payInstance->gateway('wap');

        $remoteIp = \App::environment('product', 'production') ?
                        request()->getClientIp() : '58.58.92.186';

        // 请求参数
        $options = [
            'out_trade_no' => data_get($option, 'id') . time(),
            'total_fee'    => data_get($option, 'total') * 100,
            'body'             => data_get($option, 'body', '用户付款'),    // 订单描述
            'spbill_create_ip' => $remoteIp,                                            // 支付人的 IP
//            'spbill_create_ip' => data_get($option, 'ip', '58.58.92.186'),                                            // 支付人的 IP
            'notify_url'       => data_get($option, 'notify_url'),                               // 定通知URL
            'attach'           => data_get($option, 'description', '收款'),
        ];

        //        $returnUrl = $order->getReturnUrl();
        //        if (strpos($returnUrl, '?') !== false)
        //            $returnUrl = substr($returnUrl, 0, strpos($returnUrl, '?'));

        info('微信H5支付请求参数', [$options]);

        $result = $driver->apply($options).urlencode(env('APP_URL'));

        info('微信H5支付返回值', [$result]);

        return $result;
    }

    /**
     * 微信公众号支付
     * @param $order
     * @param array $option
     * @return mixed
     */
    protected function wxMpPay(array $option)
    {
        $driver = $this->payInstance->gateway('mp');

        $params = [
            'out_trade_no' => data_get($option, 'id') . time(),
            'total_fee'    => data_get($option, 'total') * 100,
            'body'         => $option['body'],
            'openid'       => $option['openid'], // 支付人的 openID
            'notify_url'   => data_get($option, 'notify_url'), // 定义通知URL
            'attach'       => $option['description'],
        ];

        //        if (!\App::environment('product', 'production')) {
        //            $params['total_fee'] = 1;
        //        }
        info('创建微信支付订单参数', $params);

        $res = $driver->apply($params);

        info('创建微信支付订单返回值', [$res]);

        return $res;
    }

    protected function wxAppPay($option)
    {
        $remoteIp = request()->getClientIp();

        $options = [
            'out_trade_no' => data_get($option, 'id') . time(),
            'total_fee'    => data_get($option, 'total') * 100,
            'body'             => data_get($option, 'body', ''), // 订单描述
            'spbill_create_ip' => $remoteIp, // 支付人的 IP
            'notify_url'       => data_get($option, 'notify_url'), // 定义通知URL
        ];

        info('创建微信App支付订单参数', $options);

        $driver = $this->payInstance->gateway('app');
        $res    = $driver->apply($options);

        info('创建微信App支付订单返回值', [$res]);

        return $res;
    }

    /**
     * 微信公众号支付通知
     * @return mixed
     */
    public function wxMpNotify($method = 'mp', $params)
    {
        switch ($method) {
            case 'mp':
            case 'wap':
                $resultXml = file_get_contents('php://input');
//                $invalid_characters = '/[^\x9\xa\x20-\xD7FF\xE000-\xFFFD]/';
//                $resultXml = preg_replace($invalid_characters, '', $resultXml);
                info('支付结果通知', [$resultXml]);
                $driver = $this->payInstance->gateway($method);
                $res    = $driver->verify($resultXml);

                info('支付结果通知arr', [$res]);
                $outTradeNo = $res['out_trade_no'];
                if ($wxPayOrder = $this->queryOrder($outTradeNo, $method)) {
                    if (data_get($wxPayOrder, 'trade_state') != 'SUCCESS')
                        return false;
                }
                return $res;
                break;
            case 'app':
                switch ($this->driver) {
                    case 'wechat':
                        $resultXml = file_get_contents('php://input');
                        info('微信App支付结果通知', [$resultXml]);
                        $driver = $this->payInstance->gateway($method);
                        $res    = $driver->verify($resultXml);

                        $outTradeNo = $res['out_trade_no'];
                        if ($wxPayOrder = $this->queryOrder($outTradeNo, $method)) {
                            if (data_get($wxPayOrder, 'trade_state') != 'SUCCESS')
                                return false;
                        }
                        return $res;
                }
                break;
            case 'transfer':
                $resultXml = file_get_contents('php://input');
                info('提现结果通知', [$resultXml]);
                $method = 'wap';
                $driver = $this->payInstance->gateway($method);
                $res    = $driver->verify($resultXml);

                $outTradeNo = $res['out_trade_no'];
                if ($wxPayOrder = $this->queryOrder($outTradeNo, $method)) {
                    if (data_get($wxPayOrder, 'trade_state') != 'SUCCESS')
                        return false;
                }
                return $res;
                break;
            case 'refund':
                $method = 'wap';
                $outTradeNo = $params['out_trade_no'];
                $wechat = new RefundGateway($this->config['wechat']);
                if ($wxPayOrder = $wechat->queryOrder($outTradeNo)) {
                    info('退款结果', [$wxPayOrder]);
                    if (data_get($wxPayOrder, 'err_code', 'SUCCESS') != 'SUCCESS')
                        $wxPayOrder['error'] = true;
                }
                return $wxPayOrder;
                break;
            default:
                $resultXml = file_get_contents('php://input');
                info('支付结果通知', [$resultXml]);
                $driver = $this->payInstance->gateway($method);
                $res    = $driver->verify($resultXml);

                $outTradeNo = $res['out_trade_no'];
                if ($wxPayOrder = $this->queryOrder($outTradeNo, $method)) {
                    if (data_get($wxPayOrder, 'trade_state') != 'SUCCESS')
                        return false;
                }
                return $res;
                break;
        }
    }

    public function queryOrder($outTradeNo, $paymentMethod)
    {
        try {
            $result = $this->wxQueryOrder($outTradeNo, $paymentMethod);
            info('查询支付订单', [$outTradeNo, $result]);

            return $result;
        } catch (\Exception $e) {
            error('无法获取订单信息', [$outTradeNo, $paymentMethod, $e->getMessage()]);
            return false;
        }
    }
    // 微信企业付款
    protected function wxTransFerPay(array $option)
    {
        $driver = $this->payInstance->gateway('transfer');
        // 请求参数
        $options = [
            'partner_trade_no' => data_get($option, 'partner_trade_no', ''),    // 订单号
            'openid'           => data_get($option, 'openId', ''),
            'amount'           => (string)data_get($option, 'total', 0) * 100,        // 订单金额，**单位：分**
            'desc'             => data_get($option, 'desc', ''),         // 订单描述
            'spbill_create_ip' => data_get($option, 'ip', '58.58.92.186'),
            'check_name'       => 'NO_CHECK',
            'notify_url'   => data_get($option, 'notify_url'), // 定义通知URL
        ];

        info('微信企业付款请求参数', $options);

        $result = $driver->apply($options);

        info('微信企业付款返回值', [$result]);

        return $result;
    }
    // 微信企业退款
    protected function wxRefundPay(array $option)
    {
        // $driver = $this->payInstance->gateway('refund');
        // 请求参数
        $options = [
            'transaction_id'    => data_get($option, 'transaction_id'),    // 微信支付订单号
            'out_refund_no'     => data_get($option, 'out_refund_no', ''),         // 商户退款单号
            'total_fee'         => data_get($option, 'total_fee', 0) * 100,        // 订单金额，**单位：分**
            'refund_fee'        => data_get($option, 'refund_fee', 0) * 100,        // 退款金额,**单位：分**
            'notify_url'   => data_get($option, 'notify_url'), // 定义通知URL
        ];

        info('微信企业退款请求参数', $options);

        // $result = $driver->apply($options);
        $wechat = new RefundGateway($this->config['wechat']);
        $result = $wechat->apply($options);
        info('微信企业退款返回值', [$result]);

        return $result;
    }
}
